package licode.unisop.realm.application.service;

import cn.hutool.core.util.StrUtil;
import licode.unisop.provider.api.SiAuthenticationInterceptor;
import licode.unisop.provider.api.SiAuthenticationProvider;
import licode.unisop.provider.api.SiUserProvider;
import licode.unisop.provider.info.*;
import licode.unisop.realm.application.gateway.SiUserProviderManager;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 实现默认的插件管理
 *
 * @author licode
 */
@Service
public class SiUserProviderManagerDefault implements SiUserProviderManager {
    private static final String DEF_NAME = "default";
    private final ConcurrentHashMap<String, SiUserProvider> users = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, SiAuthenticationProvider> auths = new ConcurrentHashMap<>();
    private final ConcurrentHashMap<String, SiAuthenticationInterceptor> authInters = new ConcurrentHashMap<>();

    @Resource
    private SiAuthenticationProvider siAuthenticationProvider;

    @PostConstruct
    public void init() {
        auths.put(buildIdentityKey(DEF_NAME, null), siAuthenticationProvider);
    }

    @Override
    public void registerUserProvider(SiRealmReg regInfo) {
        String key = regInfo.getProviderId();
        if (!users.containsKey(key)) {
            users.put(key, regInfo.getProvider());
        } else {
            // 插件已经存在
        }
    }

    @Override
    public SiUserProvider findUserProvider(SiProviderFind findInfo) {
        String key = findInfo.getProviderId();
        return null == key ? null : users.getOrDefault(key, null);
    }

    @Override
    public void registerAuthProvider(SiAuthenticationReg regInfo) {
        String key = buildIdentityKey(regInfo.getRealmId(), regInfo.getAuthType());
        if (!auths.containsKey(key)) {
            auths.put(key, regInfo.getProvider());
        }
    }

    @Override
    public SiAuthenticationProvider findAuthProvider(SiIdentityFind findInfo) {
        String key = buildIdentityKey(findInfo.getRealmId(), findInfo.getAuthType());

        if (auths.containsKey(key)) {
            return auths.get(key);
        } else {
            key = buildIdentityKey(findInfo.getRealmId(), "");
            return auths.getOrDefault(key, siAuthenticationProvider);
        }
    }

    @Override
    public void registerAuthInterceptor(SiAuthInterceptorReg regInfo) {
        String key = buildIdentityInterceptorKey(regInfo.getRealmId(), regInfo.getPlatformId());
        if (authInters.containsKey(key)) {
            authInters.put(key, regInfo.getPlugin());
        }
    }

    @Override
    public SiAuthenticationInterceptor findAuthInterceptor(SiIdentityFind findInfo) {
        String key = buildIdentityInterceptorKey(findInfo.getRealmId(), findInfo.getPlatformId());
        return authInters.getOrDefault(key, null);
    }

    @Override
    public List<SiUserProvider> getUserProviders() {
        return new ArrayList<>(users.values());
    }

    @Override
    public List<SiAuthenticationProvider> getAuthenticationProviders() {
        return new ArrayList<>(auths.values());
    }

    private String buildUserKey(String realmId, String platId) {
        return realmId + "_$DEF";
    }

    private String buildIdentityInterceptorKey(String realmId, String platId) {
        if (StrUtil.isBlank(platId)) {
            return realmId + "_$DEF";
        } else {
            return realmId + "_" + platId + "_$DEF";
        }
    }

    private String buildIdentityKey(String realmId, String authType) {
        if (StrUtil.isBlank(authType)) {
            return realmId + "_$DEF";
        } else {
            return realmId + "_" + authType;
        }
    }
}
